home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / dpmigcc5.zip / RSX / SOURCE / DEB / UNASSMBL.C < prev    next >
C/C++ Source or Header  |  1994-12-12  |  28KB  |  1,143 lines

  1. /* This is file UNASSMBL.C
  2. **
  3. ** changed Rainer Schnitker
  4. */
  5.  
  6. /*
  7. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  8. **
  9. ** This file is distributed under the terms listed in the document
  10. ** "copying.dj", available from DJ Delorie at the address above.
  11. ** A copy of "copying.dj" should accompany this file; if not, a copy
  12. ** should be available from where this file was obtained.  This file
  13. ** may not be distributed without a verbatim copy of "copying.dj".
  14. **
  15. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  16. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. */
  18.  
  19. #include <stdio.h>
  20. #include <string.h>
  21.  
  22. #ifdef __GO32__
  23. #include <sys/_reg.h>
  24. #else
  25. #include <sys/reg.h>
  26. #endif
  27.  
  28. #include "unassmbl.h"
  29. #include "syms.h"
  30. #include "ansi.h"
  31.  
  32. extern int ptrace_get_register(int);
  33. extern read_memory(unsigned long, char *, int);
  34. #define read_child(a,b,c) read_memory(a,b,c)
  35.  
  36. typedef unsigned char       word8;
  37. typedef unsigned short       word16;
  38. typedef unsigned long       word32;
  39. typedef char           int8;
  40. typedef short           int16;
  41. typedef long           int32;
  42.  
  43. #define SOURCE_LIST
  44.  
  45. int seg_size=32;
  46.  
  47. static word8 buf[20];
  48. static word32 vaddr;
  49. static int bufp, bufe;
  50. static char ubuf[100], *ubufp;
  51. static col;
  52.  
  53. static ua_str(char *s);
  54.  
  55. /* Percent tokens in strings:
  56.    First char after '%':
  57.     A - direct address
  58.     C - reg of r/m picks control register
  59.     D - reg of r/m picks debug register
  60.     E - r/m picks operand
  61.     F - flags register
  62.     G - reg of r/m picks general register
  63.     I - immediate data (takes extended size, data size)
  64.     J - relative IP offset
  65.     M - r/m picks memory
  66.     O - no r/m, offset only
  67.     R - mod of r/m picks register only
  68.     S - reg of r/m picks segment register
  69.     T - reg of r/m picks test register
  70.     X - DS:ESI
  71.     Y - ES:EDI
  72.     2 - prefix of two-byte opcode
  73.     e - put in 'e' if use32 (second char is part of reg name)
  74.         put in 'w' for use16 or 'd' for use32 (second char is 'w')
  75.     f - floating point (second char is esc value)
  76.     g - do r/m group 'n'
  77.     p - prefix
  78.     s - size override (second char is a,o)
  79.     + - make default signed
  80.    Second char after '%':
  81.     a - two words in memory (BOUND)
  82.     b - byte
  83.     c - byte or word
  84.     d - dword
  85.     p - 32 or 48 bit pointer
  86.     s - six byte pseudo-descriptor
  87.     v - word or dword
  88.     w - word
  89.     F - use floating regs in mod/rm
  90.     + - always sign
  91.     - - sign if negative
  92.     1-8 - group number, esc value, etc
  93. */
  94.  
  95. char *opmap1[] = {
  96. /* 0 */
  97.   "add %Eb,%Gb", "add %Ev,%Gv", "add %Gb,%Eb", "add %Gv,%Ev",
  98.   "add al,%I-bb", "add %eax,%I-vv", "push es", "pop es",
  99.   "or %Eb,%Gb", "or %Ev,%Gv", "or %Gb,%Eb", "or %Gv,%Ev",
  100.   "or al,%Ibb", "or %eax,%Ivv", "push cs", "%2 ",
  101. /* 1 */
  102.   "adc %Eb,%Gb", "adc %Ev,%Gv", "adc %Gb,%Eb", "adc %Gv,%Ev",
  103.   "adc al,%I-bb", "adc %eax,%I-vv", "push ss", "pop ss",
  104.   "sbb %Eb,%Gb", "sbb %Ev,%Gv", "sbb %Gb,%Eb", "sbb %Gv,%Ev",
  105.   "sbb al,%I-bb", "sbb %eax,%I-vv", "push ds", "pop ds",
  106. /* 2 */
  107.   "and %Eb,%Gb", "and %Ev,%Gv", "and %Gb,%Eb", "and %Gv,%Ev",
  108.   "and al,%Ibb", "and %eax,%Ivv", "%pe", "daa",
  109.   "sub %Eb,%Gb", "sub %Ev,%Gv", "sub %Gb,%Eb", "sub %Gv,%Ev",
  110.   "sub al,%I-bb", "sub %eax,%I-vv", "%pc", "das",
  111. /* 3 */
  112.   "xor %Eb,%Gb", "xor %Ev,%Gv", "xor %Gb,%Eb", "xor %Gv,%Ev",
  113.   "xor al,%Ibb", "xor %eax,%Ivv", "%ps", "aaa",
  114.   "cmp %Eb,%Gb", "cmp %Ev,%Gv", "cmp %Gb,%Eb", "cmp %Gv,%Ev",
  115.   "cmp al,%I-bb", "cmp %eax,%I-vv", "%pd", "aas",
  116. /* 4 */
  117.   "inc %eax", "inc %ecx", "inc %edx", "inc %ebx",
  118.   "inc %esp", "inc %ebp", "inc %esi", "inc %edi",
  119.   "dec %eax", "dec %ecx", "dec %edx", "dec %ebx",
  120.   "dec %esp", "dec %ebp", "dec %esi", "dec %edi",
  121. /* 5 */
  122.   "push %eax", "push %ecx", "push %edx", "push %ebx",
  123.   "push %esp", "push %ebp", "push %esi", "push %edi",
  124.   "pop %eax", "pop %ecx", "pop %edx", "pop %ebx",
  125.   "pop %esp", "pop %ebp", "pop %esi", "pop %edi",
  126. /* 6 */
  127.   "pusha", "popa", "bound %Gv,%Ma", "arpl %Ew,%Rw",
  128.   "%pf", "%pg", "%so", "%sa",
  129.   "push %I-vv", "imul %Gv=%Ev*%I-vv", "push %I-vb", "imul %Gv=%Ev*%I-vb",
  130.   "insb %Yb,dx", "ins%ew %Yv,dx", "outsb dx,%Xb", "outs%ew dx,%Xv",
  131. /* 7 */
  132.   "jo %Jb", "jno %Jb", "jc %Jb", "jnc %Jb",
  133.   "jz %Jb", "jnz %Jb", "jbe %Jb", "jnbe %Jb",
  134.   "js %Jb", "jns %Jb", "jpe %Jb", "jpo %Jb",
  135.   "jl %Jb", "jge %Jb", "jle %Jb", "jg %Jb",
  136. /* 8 */
  137.   "%g1 %Eb,%Ibb", "%g1 %Ev,%Ivv", "mov al,%Ibb", "%g1 %Ev,%Ivb",
  138.   "test %Eb,%Gb", "test %Ev,%Gv", "xchg %Eb,%Gb", "xchg %Ev,%Gv",
  139.   "mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev",
  140.   "mov %Ew,%Sw", "lea %Gv,%M ", "mov %Sw,%Ew", "pop %Ev",
  141. /* 9 */
  142.   "nop", "xchg %eax,%ecx", "xchg %eax,%edx", "xchg %eax,%ebx",
  143.   "xchg %eax,%esp", "xchg %eax,%ebp", "xchg %eax,%esi", "xchg %eax,%edi",
  144.   "cbw", "cwd", "call %Ap", "fwait",
  145.   "push %eflags", "pop %eflags", "sahf", "lahf",
  146. /* a */
  147.   "mov al,%Ob", "mov %eax,%Ov", "mov %Ob,al", "mov %Ov,%eax",
  148.   "movsb %Xb,%Yb", "movs%ew %Xv,%Yv", "cmpsb %Xb,%Yb", "cmps%ew %Xv,%Yv",
  149.   "test al,%Ibb", "test %eax,%Ivv", "stosb %Yb,al", "stos%ew %Yv,%eax",
  150.   "lodsb al,%Xb", "lods%ew %eax,%Xv", "scasb al,%Xb", "scas%ew %eax,%Xv",
  151. /* b */
  152.   "mov al,%Ibb", "mov cl,%Ibb", "mov dl,%Ibb", "mov bl,%Ibb",
  153.   "mov ah,%Ibb", "mov ch,%Ibb", "mov dh,%Ibb", "mov bh,%Ibb",
  154.   "mov %eax,%I-vv", "mov %ecx,%I-vv", "mov %edx,%I-vv", "mov %ebx,%I-vv",
  155.   "mov %esp,%Ivv", "mov %ebp,%Ivv", "mov %esi,%I-vv", "mov %edi,%I-vv",
  156. /* c */
  157.   "%g2 %Eb,%Ibb", "%g2 %Ev,%Ibb", "ret %Iw", "ret",
  158.   "les %Gv,%Mp", "lds %Gv,%Mp", "mov %Eb,%Ibb", "mov %Ev,%I-vv",
  159.   "enter %Iww,%Ibb", "leave", "retf %Iww", "retf",
  160.   "int 3", "int %Ibb", "into", "iret",
  161. /* d */
  162.   "%g2 %Eb,1", "%g2 %Ev,1", "%g2 %Eb,cl", "%g2 %Ev,cl",
  163.   "aam", "aad", 0, "xlat",
  164.   "%f0", "%f1", "%f2", "%f3",
  165.   "%f4", "%f5", "%f6", "%f7",
  166. /* e */
  167.   "loopne %Jb", "loope %Jb", "loop %Jb", "jcxz %Jb",
  168.   "in al,%Ibb", "in %eax,%Ibb", "out %Ibb,al", "out %Ibb,%eax",
  169.   "call %Jv", "jmp %Jv", "jmp %Ap", "jmp %Jb",
  170.   "in al,dx", "in %eax,dx", "out dx,al", "out dx,%eax",
  171. /* f */
  172.   "lock %p ", 0, "repne %p ", "rep(e) %p ",
  173.   "hlt", "cmc", "%g3", "%g0",
  174.   "clc", "stc", "cli", "sti",
  175.   "cld", "std", "%g4", "%g5"
  176.   };
  177.  
  178. char *second[] = {
  179. /* 0 */
  180.   "%g6", "%g7", "lar %Gv,%Ew", "lsl %Gv,%Ew", 0, 0, "clts", 0,
  181.   0, 0, 0, 0, 0, 0, 0, 0,
  182. /* 1 */
  183.   0, 0, 0, 0, 0, 0, 0, 0,
  184.   0, 0, 0, 0, 0, 0, 0, 0,
  185. /* 2 */
  186.   "mov %Rd,%Cd", "mov %Rd,%Dd", "mov %Cd,%Rd", "mov %Dd,%Rd",
  187.   "mov %Rd,%Td", 0, "mov %Td,%Rd", 0,
  188.   0, 0, 0, 0, 0, 0, 0, 0,
  189. /* 3 */
  190.   0, 0, 0, 0, 0, 0, 0, 0,
  191.   0, 0, 0, 0, 0, 0, 0, 0,
  192.   0, 0, 0, 0, 0, 0, 0, 0,
  193.   0, 0, 0, 0, 0, 0, 0, 0,
  194.   0, 0, 0, 0, 0, 0, 0, 0,
  195.   0, 0, 0, 0, 0, 0, 0, 0,
  196.   0, 0, 0, 0, 0, 0, 0, 0,
  197.   0, 0, 0, 0, 0, 0, 0, 0,
  198.   0, 0, 0, 0, 0, 0, 0, 0,
  199.   0, 0, 0, 0, 0, 0, 0, 0,
  200. /* 8 */
  201.   "jo %Jv", "jno %Jv", "jc %Jv", "jnc %Jv",
  202.   "jz %Jv", "jnz %Jv", "jbe %Jv", "jnbe %Jv",
  203.   "js %Jv", "jns %Jv", "jpe %Jv", "jpo %Jv",
  204.   "jl %Jv", "jge %Jv", "jle %Jv", "jg %Jv",
  205. /* 9 */
  206.   "seto %Eb", "setno %Eb", "setnc %Eb", "setc %Eb",
  207.   "setz %Eb", "setnz %Eb", "setbe %Eb", "setnbe %Eb",
  208.   "sets %Eb", "setns %Eb", "setp %Eb", "setnp %Eb",
  209.   "setl %Eb", "setge %Eb", "setle %Eb", "setg %Eb",
  210. /* a */
  211.   "push fs", "pop fs", 0, "bt %Ev,%Gv",
  212.   "shld %Ev,%Gv,%Ibb", "shld %Ev,%Gv,cl", 0, 0,
  213.   "push gs", "pop gs", 0, "bts %Ev,%Gv",
  214.   "shrd %Ev,%Gv,%Ibb", "shrd %Ev,%Gv,cl", 0, "imul %Gv,%Ev",
  215. /* b */
  216.   0, 0, "lss %Mp", "btr %Ev,%Gv",
  217.   "lfs %Mp", "lgs %Mp", "movzx %Gv,%Eb", "movzx %Gv,%Ew",
  218.   0, 0, "%g8 %Ev,%Ibb", "btc %Ev,%Gv",
  219.   "bsf %Gv,%Ev", "bsr %Gv,%Ev", "movsx %Gv,%Eb", "movsx %Gv,%Ew",
  220. /* c */
  221.   0, 0, 0, 0, 0, 0, 0, 0,
  222.   0, 0, 0, 0, 0, 0, 0, 0,
  223.   0, 0, 0, 0, 0, 0, 0, 0,
  224.   0, 0, 0, 0, 0, 0, 0, 0,
  225.   0, 0, 0, 0, 0, 0, 0, 0,
  226.   0, 0, 0, 0, 0, 0, 0, 0,
  227.   0, 0, 0, 0, 0, 0, 0, 0,
  228.   0, 0, 0, 0, 0, 0, 0, 0,
  229.   };
  230.  
  231. char *groups[][8] = {      /* group 0 is group 3 for %Ev set */
  232.   { "test %Ev,%Ivv", "test %Ev,%Ivv,", "not %Ev", "neg %Ev",
  233.     "mul %eax,%Ev", "imul %eax,%Ev", "div %eax,%Ev", "idiv %eax,%Ev" },
  234.   { "add%+-", "or", "adc%+-", "sbb%+-", "and", "sub%+-", "xor", "cmp%+-" },
  235.   { "rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar" },
  236.   { "test %Eb,%Ibb", "test %Eb,%Ibb,", "not %Eb", "neg %Eb",
  237.     "mul al,%Eb", "imul al,%Eb", "div al,%Eb", "idiv al,%Eb" },
  238.   { "inc %Eb", "dec %Eb", 0, 0, 0, 0, 0, 0 },
  239.   { "inc %Ev", "dec %Ev", "call %Ev", "call %Ep",
  240.     "jmp %Ev", "jmp %Ep", "push %Ev", 0 },
  241.   { "sldt %Ew", "str %Ew", "lldt %Ew", "ltr %Ew",
  242.     "verr %Ew", "verw %Ew", 0, 0 },
  243.   { "sgdt %Ms", "sidt %Ms", "lgdt %Ms", "lidt %Ms",
  244.     "smsw %Ew", 0, "lmsw %Ew", 0 },
  245.   { 0, 0, 0, 0, "bt", "bts", "btr", "btc" }
  246.   };
  247.  
  248. /* zero here means invalid.  If first entry starts with '*', use st(i) */
  249. /* no assumed %EFs here.  Indexed by rm(modrm()) */
  250. char *f0[] = {0, 0, 0, 0, 0, 0, 0, 0};
  251. char *fop_9[]  = { "*fxch st,%GF" };
  252. char *fop_10[] = { "fnop", 0, 0, 0, 0, 0, 0, 0 };
  253. char *fop_12[] = { "fchs", "fabs", 0, 0, "ftst", "fxam", 0, 0 };
  254. char *fop_13[] = { "fld1", "fldl2t", "fldl2e", "fldpi",
  255.            "fldlg2", "fldln2", "fldz", 0 };
  256. char *fop_14[] = { "f2xm1", "fyl2x", "fptan", "fpatan",
  257.            "fxtract", "fprem1", "fdecstp", "fincstp" };
  258. char *fop_15[] = { "fprem", "fyl2xp1", "fsqrt", "fsincos",
  259.            "frndint", "fscale", "fsin", "fcos" };
  260. char *fop_21[] = { 0, "fucompp", 0, 0, 0, 0, 0, 0 };
  261. char *fop_28[] = { 0, 0, "fclex", "finit", 0, 0, 0, 0 };
  262. char *fop_32[] = { "*fadd %GF,st" };
  263. char *fop_33[] = { "*fmul %GF,st" };
  264. char *fop_36[] = { "*fsubr %GF,st" };
  265. char *fop_37[] = { "*fsub %GF,st" };
  266. char *fop_38[] = { "*fdivr %GF,st" };
  267. char *fop_39[] = { "*fdiv %GF,st" };
  268. char *fop_40[] = { "*ffree %GF" };
  269. char *fop_42[] = { "*fst %GF" };
  270. char *fop_43[] = { "*fstp %GF" };
  271. char *fop_44[] = { "*fucom %GF" };
  272. char *fop_45[] = { "*fucomp %GF" };
  273. char *fop_48[] = { "*faddp %GF,st" };
  274. char *fop_49[] = { "*fmulp %GF,st" };
  275. char *fop_51[] = { 0, "fcompp", 0, 0, 0, 0, 0, 0 };
  276. char *fop_52[] = { "*fsubrp %GF,st" };
  277. char *fop_53[] = { "*fsubp %GF,st" };
  278. char *fop_54[] = { "*fdivrp %GF,st" };
  279. char *fop_55[] = { "*fdivp %GF,st" };
  280. char *fop_60[] = { "fstsw ax", 0, 0, 0, 0, 0, 0, 0 };
  281.  
  282. char **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means undefined */
  283.   0, 0, 0, 0, 0, 0, 0, 0,
  284.   0, fop_9, fop_10, 0, fop_12, fop_13, fop_14, fop_15,
  285.   f0, f0, f0, f0, f0, fop_21, f0, f0,
  286.   f0, f0, f0, f0, fop_28, f0, f0, f0,
  287.   fop_32, fop_33, f0, f0, fop_36, fop_37, fop_38, fop_39,
  288.   fop_40, f0, fop_42, fop_43, fop_44, fop_45, f0, f0,
  289.   fop_48, fop_49, f0, fop_51, fop_52, fop_53, fop_54, fop_55,
  290.   f0, f0, f0, f0, fop_60, f0, f0, f0,
  291.   };
  292.  
  293. char *floatops[] = { /* assumed " %EF" at end of each.  mod != 3 only */
  294. /*00*/ "fadd", "fmul", "fcom", "fcomp",
  295.        "fsub", "fsubr", "fdiv", "fdivr",
  296. /*08*/ "fld", 0, "fst", "fstp",
  297.        "fldenv", "fldcw", "fstenv", "fstcw",
  298. /*16*/ "fiadd", "fimul", "ficomw", "ficompw",
  299.        "fisub", "fisubr", "fidiv", "fidivr",
  300. /*24*/ "fild", 0, "fist", "fistp",
  301.        "frstor", "fldt", 0, "fstpt",
  302. /*32*/ "faddq", "fmulq", "fcomq", "fcompq",
  303.        "fsubq", "fsubrq", "fdivq", "fdivrq",
  304. /*40*/ "fldq", 0, "fstq", "fstpq",
  305.        0, 0, "fsave", "fstsww",
  306. /*48*/ "fiaddw", "fimulw", "ficomw", "ficompw",
  307.        "fisubw", "fisubrw", "fidivw", "fidivr",
  308. /*56*/ "fildw", 0, "fistw", "fistpw",
  309.        "fbldt", "fildq", "fbstpt", "fistpq"
  310.   };
  311.  
  312. static word8 getbyte(void)
  313. {
  314.   int s;
  315.   if (bufp >= bufe)
  316.   {
  317.     s = 20;
  318.     if ((vaddr & 0xfff) + s > 0x1000)
  319.       s = 0x1000 - (vaddr & 0xfff);
  320.     read_child(vaddr, buf, s);
  321.     bufe = s;
  322.     bufp = 0;
  323.   }
  324.   vaddr++;
  325.   printf("%02x", buf[bufp]);
  326.   col+=2;
  327.   return buf[bufp++];
  328. }
  329.  
  330. static int default_pick_sign;
  331.  
  332. static prefix;
  333. static modrmv;
  334. static sibv;
  335. static opsize;
  336. static addrsize;
  337.  
  338. static modrm(void)
  339. {
  340.   if (modrmv == -1)
  341.     modrmv = getbyte();
  342.   return modrmv;
  343. }
  344.  
  345. static sib(void)
  346. {
  347.   if (sibv == -1)
  348.     sibv = getbyte();
  349.   return sibv;
  350. }
  351.  
  352. #define mod(a)    (((a)>>6)&7)
  353. #define reg(a)    (((a)>>3)&7)
  354. #define rm(a)    ((a)&7)
  355. #define ss(a)    (((a)>>6)&7)
  356. #define indx(a) (((a)>>3)&7)
  357. #define base(a) ((a)&7)
  358.  
  359. /*------------------------------------------------------------------------*/
  360. uprintf(char *s, ...)
  361. {
  362.   char **a = &s;
  363.   vsprintf(ubufp, s, a+1);
  364.   while (*ubufp) ubufp++;
  365. }
  366.  
  367. uputchar(char c)
  368. {
  369.   if (c == '\t')
  370.   {
  371.     do {
  372.       *ubufp++ = ' ';
  373.     } while ((ubufp-ubuf) % 8);
  374.   }
  375.   else
  376.     *ubufp++ = c;
  377.   *ubufp = 0;
  378. }
  379.  
  380. /*------------------------------------------------------------------------*/
  381. int bytes(char c)
  382. {
  383.   switch (c)
  384.   {
  385.     case 'b':
  386.       return 1;
  387.     case 'w':
  388.       return 2;
  389.     case 'd':
  390.       return 4;
  391.     case 'v':
  392.       if (opsize == 32)
  393.     return 4;
  394.       else
  395.     return 2;
  396.   }
  397.   return 0;
  398. }
  399.  
  400. /*------------------------------------------------------------------------*/
  401. static ohex(char c, int extend, int optional, int defsize, int sign)
  402. {
  403.   static char *formats[4] = { "%#x", "%d", "%+d", "%+d" };
  404.   char *fmt;
  405.   int n=0, s=0, i, j;
  406.   int32 delta;
  407.   unsigned char buf[6];
  408.   char *name;
  409.   fmt = formats[sign];
  410.  
  411.   switch (c)
  412.   {
  413.     case 'a':
  414.       break;
  415.     case 'b':
  416.       n = 1;
  417.       break;
  418.     case 'w':
  419.       n = 2;
  420.       break;
  421.     case 'd':
  422.       n = 4;
  423.       break;
  424.     case 's':
  425.       n = 6;
  426.       break;
  427.     case 'c':
  428.     case 'v':
  429.       if (defsize == 32)
  430.     n = 4;
  431.       else
  432.     n = 2;
  433.       break;
  434.     case 'p':
  435.       if (defsize == 32)
  436.     n = 6;
  437.       else
  438.     n = 4;
  439.       s = 1;
  440.       break;
  441.     case 'x':
  442.       return;
  443.   }
  444.   for (i=0; i<n; i++)
  445.     buf[i] = getbyte();
  446.   for (; i<extend; i++)
  447.     buf[i] = (buf[i-1] & 0x80) ? 0xff : 0;
  448.   if (s)
  449.   {
  450.     uprintf("0x%02x%02x:", buf[n-1], buf[n-2]);
  451.     n -= 2;
  452.   }
  453.   switch (n)
  454.   {
  455.     case 1:
  456.       delta = *(signed char *)buf;
  457.       break;
  458.    case 2:
  459.       delta = *(signed short *)buf;
  460.       break;
  461.     case 4:
  462.       delta = *(signed long *)buf;
  463.       break;
  464.   }
  465.   if (extend > n)
  466.   {
  467.     if (delta || !optional)
  468.     {
  469.       uprintf(fmt, delta);
  470.     }
  471.     return;
  472.   }
  473.   if ((n == 4) && sign < 2)
  474.   {
  475.     name = syms_val2name(delta, &delta);
  476.     if (name)
  477.     {
  478.       uprintf("%s", name);
  479.       if (delta)
  480.     uprintf("+%lu", delta);
  481.       return;
  482.     }
  483.   }
  484.   switch (n)
  485.   {
  486.     case 1:
  487.       uprintf(fmt, (unsigned char)delta);
  488.       break;
  489.     case 2:
  490.       uprintf(fmt, (unsigned short)delta);
  491.       break;
  492.     case 4:
  493.       uprintf(fmt, (unsigned long)delta);
  494.       break;
  495.   }
  496. }
  497.  
  498. /*------------------------------------------------------------------------*/
  499.  
  500. static char *reg_names[3][8]={
  501.    "al","cl","dl","bl","ah","ch","dh","bh",
  502.   "ax","cx","dx","bx","sp","bp","si","di",
  503.   "eax","ecx","edx","ebx","esp","ebp","esi","edi" };
  504.  
  505. static int reg_index[8]={ EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI};
  506.  
  507. reg_name(int which, char size)
  508. {
  509.   if (size == 'F')
  510.   {
  511.     uprintf("st(%d)", which);
  512.     return;
  513.   }
  514.   if (((size == 'v') && (opsize == 32)) || (size == 'd'))
  515.   {
  516.     uputchar('e');
  517.   }
  518.   if (size == 'b')
  519.   {
  520.     uputchar("acdbacdb"[which]);
  521.     uputchar("llllhhhh"[which]);
  522.   }
  523.   else
  524.   {
  525.     uputchar("acdbsbsd"[which]);
  526.     uputchar("xxxxppii"[which]);
  527.   }
  528. }
  529.  
  530. /*------------------------------------------------------------------------*/
  531. do_sib(m)
  532. {
  533.   static char *i_str[] = {
  534.     "+eax", "+ecx", "+edx", "+ebx", "", "+ebp", "+esi", "+edi" };
  535.   int pick_signed = default_pick_sign;
  536.   int s, i, b, extra=0;
  537.   s = ss(sib());
  538.   i = indx(sib());
  539.   b = base(sib());
  540.   if (b == 5)
  541.   {
  542.       if (m == 0)
  543.       {
  544.     ua_str("%p:[");
  545.     ohex('d', 4, 0, addrsize, 1);
  546.       }
  547.       else
  548.       {
  549.     ua_str("%p:[ebp");
  550.     pick_signed |= 2;
  551.       }
  552.   }
  553.   else
  554.   {
  555.     static char *sib_str[] = {
  556.       "%p:[eax", "%p:[ecx", "%p:[edx", "%p:[ebx", "%p:[esp", 0, "%p:[esi", "%p:[edi" };
  557.     pick_signed |= 2;
  558.     ua_str(sib_str[b]);
  559.     if ((b == i) && (b != 4) && (i != 5))
  560.       extra = 1;
  561.   }
  562.   if (extra == 0)
  563.   {
  564.     pick_signed |= 2;
  565.     uprintf(i_str[i]);
  566.   }
  567.   if (i != 4 && s)
  568.     uprintf("*%d", (1<<s)+extra);
  569.   return pick_signed;
  570. }
  571.  
  572. /*------------------------------------------------------------------------*/
  573.  
  574. static int modrm_extend;
  575.  
  576. do_modrm(char t)
  577. {
  578.   int m = mod(modrm());
  579.   int r = rm(modrm());
  580.   int extend = (addrsize == 32) ? 4 : 2;
  581.   int pick_signed = default_pick_sign;
  582.   if (m == 3)
  583.   {
  584.     reg_name(r, t);
  585.     return;
  586.   }
  587.   if ((m == 0) && (r == 5) && (addrsize == 32))
  588.   {
  589.     ua_str("%p:[");
  590.     ohex('d', extend, 0, addrsize, 0);
  591.     uputchar(']');
  592.     return;
  593.   }
  594.   if ((m == 0) && (r == 6) && (addrsize == 16))
  595.   {
  596.     ua_str("%p:[");
  597.     ohex('w', extend, 0, addrsize, 0);
  598.     uputchar(']');
  599.     return;
  600.   }
  601.   if ((addrsize != 32) || (r != 4))
  602.     ua_str("%p:[");
  603.   if (addrsize == 16)
  604.   {
  605.     static char *r_str[] = {
  606.       "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx" };
  607.     uprintf(r_str[r]);
  608.     pick_signed |= 2;
  609.   }
  610.   else
  611.   {
  612.     if (r == 4)
  613.       pick_signed |= do_sib(m);
  614.     else
  615.     {
  616.       uprintf(reg_names[2][r]);
  617.       pick_signed |= 2;
  618.     }
  619.   }
  620.   modrm_extend = extend;
  621.   ohex("xbv"[m], extend, 1, addrsize, pick_signed);
  622.   uputchar(']');
  623. }
  624.  
  625. /*------------------------------------------------------------------------*/
  626. static floating_point(int e1)
  627. {
  628.   int esc = e1*8 + reg(modrm());
  629.   if (mod(modrm()) == 3)
  630.   {
  631.     if (fspecial[esc])
  632.     {
  633.       if (fspecial[esc][0] && (fspecial[esc][0][0] == '*'))
  634.       {
  635.     ua_str(fspecial[esc][0]+1);
  636.       }
  637.       else
  638.       {
  639.     ua_str(fspecial[esc][rm(modrm())]);
  640.       }
  641.     }
  642.     else
  643.     {
  644.       ua_str(floatops[esc]);
  645.       ua_str(" %EF");
  646.     }
  647.   }
  648.   else
  649.   {
  650.     ua_str(floatops[esc]);
  651.     ua_str(" %EF");
  652.   }
  653. }
  654.  
  655. /*------------------------------------------------------------------------*/
  656. static percent(char c, char **tptr)
  657. {
  658.   word32 vofs, v, delta;
  659.   char *name;
  660.   int default_signed = default_pick_sign;
  661.   char t = *(*tptr)++, it;
  662.   int extend = (addrsize == 32) ? 4 : 2;
  663.   int iextend;
  664.  
  665.   if (c != '+')
  666.   {
  667.     if (t == '-')
  668.     {
  669.       default_signed = 1;
  670.       t = *(*tptr)++;
  671.     }
  672.     else if (t == '+')
  673.     {
  674.       default_signed = 2;
  675.       t = *(*tptr)++;
  676.     }
  677.   }
  678.   switch (c)
  679.   {
  680.     case 'A':
  681.       ohex(t, extend, 0, addrsize, 0);
  682.       break;
  683.     case 'C':
  684.       uprintf("cr%d", reg(modrm()));
  685.       break;
  686.     case 'D':
  687.       uprintf("dr%d", reg(modrm()));
  688.       break;
  689.     case 'E':
  690.       do_modrm(t);
  691.       break;
  692.     case 'G':
  693.       if (t == 'F')
  694.     reg_name(rm(modrm()), t);
  695.       else
  696.     reg_name(reg(modrm()), t);
  697.       break;
  698.     case 'I':
  699.       it = *(*tptr)++;
  700.       switch (t)
  701.       {
  702.     case 'b':
  703.       iextend = 1;
  704.       break;
  705.     case 'v':
  706.       iextend = extend;
  707.       break;
  708.     default:
  709.       iextend = 0;
  710.       break;
  711.       }
  712.       ohex(it, iextend, 0, opsize, default_signed);
  713.       break;
  714.     case 'J':
  715.       switch (bytes(t))
  716.       {
  717.     case 1:
  718.       vofs = (int8)getbyte();
  719.       break;
  720.     case 2:
  721.       vofs = getbyte();
  722.       vofs += getbyte()<<8;
  723.       vofs = (int16)vofs;
  724.       break;
  725.     case 4:
  726.       vofs = (word32)getbyte();
  727.       vofs |= (word32)getbyte() << 8;
  728.       vofs |= (word32)getbyte() << 16;
  729.       vofs |= (word32)getbyte() << 24;
  730.       break;
  731.       }
  732.       name = syms_val2name(vofs+vaddr, &delta);
  733.       uprintf("%s", name);
  734.       if (delta)
  735.     uprintf("+%lu (0x%lx %c)", delta, vofs+vaddr,
  736.         (vofs & 0x80000000L) ? 0x1e : 0x1f);
  737.       break;
  738.     case 'M':
  739.       do_modrm(t);
  740.       break;
  741.     case 'O':
  742.       ua_str("%p:[");
  743.       ohex(t, extend, 0, addrsize, 0);
  744.       uputchar(']');
  745.       break;
  746.     case 'R':
  747.       do_modrm(t);
  748.       break;
  749.     case 'S':
  750.       uputchar("ecsdfg"[reg(modrm())]);
  751.       uputchar('s');
  752.       break;
  753.     case 'T':
  754.       uprintf("tr%d", reg(modrm()));
  755.       break;
  756.     case 'X':
  757.       uprintf("ds:[");
  758.       if (addrsize == 32)
  759.     uputchar('e');
  760.       uprintf("si]");
  761.       break;
  762.     case 'Y':
  763.       uprintf("es:[");
  764.       if (addrsize == 32)
  765.     uputchar('e');
  766.       uprintf("di]");
  767.       break;
  768.     case '2':
  769.       ua_str(second[getbyte()]);
  770.       break;
  771.     case 'e':
  772.       if (opsize == 32)
  773.       {
  774.     if (t == 'w')
  775.       uputchar('d');
  776.     else
  777.     {
  778.       uputchar('e');
  779.       uputchar(t);
  780.     }
  781.       }
  782.       else
  783.     uputchar(t);
  784.       break;
  785.     case 'f':
  786.       floating_point(t-'0');
  787.       break;
  788.     case 'g':
  789.       ua_str(groups[t-'0'][reg(modrm())]);
  790.       break;
  791.     case 'p':
  792.       switch (t)
  793.       {
  794.     case 'c':
  795.     case 'd':
  796.     case 'e':
  797.     case 'f':
  798.     case 'g':
  799.     case 's':
  800.       prefix = t;
  801.       ua_str(opmap1[getbyte()]);
  802.       break;
  803.     case ':':
  804.       if (prefix)
  805.         uprintf("%cs:", prefix);
  806.       break;
  807.     case ' ':
  808.       ua_str(opmap1[getbyte()]);
  809.       break;
  810.       }
  811.       break;
  812.     case 's':
  813.       switch (t)
  814.       {
  815.     case 'a':
  816.       addrsize = 48 - addrsize;
  817.       ua_str(opmap1[getbyte()]);
  818.       break;
  819.     case 'o':
  820.       opsize = 48 - opsize;
  821.       ua_str(opmap1[getbyte()]);
  822.       break;
  823.       }
  824.       break;
  825.     case '+':
  826.       switch (t)
  827.       {
  828.     case '-':
  829.       default_pick_sign = 1;
  830.       break;
  831.     case '+':
  832.       default_pick_sign = 2;
  833.       break;
  834.     default:
  835.       default_pick_sign = 0;
  836.       break;
  837.       }
  838.   }
  839. }
  840.  
  841. static ua_str(char *s)
  842. {
  843.   int c;
  844.   if (s == 0)
  845.   {
  846.     uprintf("<invalid>");
  847.     return;
  848.   }
  849.   while ((c = *s++) != 0)
  850.   {
  851.     if (c == '%')
  852.     {
  853.       c = *s++;
  854.       percent(c, &s);
  855.     }
  856.     else
  857.       if (c == ' ')
  858.     uputchar('\t');
  859.       else
  860.     uputchar(c);
  861.   }
  862. }
  863.  
  864. #ifdef SOURCE_LIST
  865. /*
  866. ** A little brute force hacking and hey presto! A source debugger!
  867. ** Courtesy of Kent Williams williams@herky.cs.uiowa.edu
  868. **
  869. ** KNOWN BUGS:
  870. ** The program will summarily terminate if you run out
  871. ** of memory while you're looking for all the line offsets.  Since
  872. ** a two thousand line source file only creats an 8K array, and the
  873. ** symbol table goes into virtual memory, this shouldn't happen too
  874. ** often.
  875. **
  876. ** One file is left open for reading indefinitely.
  877. */
  878. #include <stdlib.h>
  879. #include <string.h>
  880. /*
  881. ** keep the source line offsets in virtual memory, so you can
  882. ** debug big programs
  883. */
  884. extern word32 salloc(word32 size);
  885. #define symsput(where,ptr,size)     memput(where,ptr,size)
  886. #define symsget(where,ptr,size)     memget(where,ptr,size)
  887.  
  888. /*
  889. ** for each file encountered, keep an array of line start offsets
  890. ** so you can seek into the file to display the current line.
  891. */
  892. typedef struct {
  893.     char *filename;
  894.     long *offsets;
  895. } line_info;
  896.  
  897. static line_info *files;
  898. static last_file = 0;
  899.  
  900. /*
  901. ** add_file -- add a file to the source line database
  902. */
  903. static int
  904. add_file(char *name) {
  905.     FILE *f = fopen(name,"rb");
  906.     char c;
  907.     long *lines,curpos;
  908.     unsigned curline = 0;
  909.  
  910.     if(!f)
  911.         return -1;
  912.  
  913.     if (files == 0)
  914.       files = (line_info *)malloc(sizeof(line_info));
  915.     else
  916.       files = realloc(files, (last_file+1) * sizeof(line_info));
  917.  
  918.     files[last_file].filename = strdup(name);
  919.  
  920.     /*
  921.     ** build an array of line offsets in real memory.
  922.     */
  923.     lines = malloc(sizeof(long));
  924.     lines[curline++] = curpos = 0L;
  925.  
  926.     while((c = getc(f)) != EOF) {
  927.         curpos++;
  928.         if(c == '\n') {
  929.             lines = realloc(lines,sizeof(long)*(curline+1));
  930.             lines[curline++] = curpos;
  931.         }
  932.     }
  933.     /*
  934.     ** now move the whole array into virtual memory
  935.     */
  936.     files[last_file].offsets = lines;
  937.     fclose(f);
  938.  
  939.     last_file++;
  940.     return 0;
  941. }
  942.  
  943. static line_info *
  944. find_file(char *name) {
  945.     int i;
  946.     for(i = 0; i < last_file; i++)
  947.         if(strcmp(name,files[i].filename) == 0)
  948.             return &files[i];
  949.     if(add_file(name) == -1)
  950.             return NULL;
  951.     return find_file(name);
  952. }
  953.  
  954. /*
  955. ** myfopen -- cache the most recently accessed source file
  956. ** so you aren't constantly reopening a new file
  957. */
  958. static FILE *
  959. myfopen(char *name) {
  960.     static char fname[80] = "";
  961.     static FILE *current = NULL;
  962.     if(current != NULL && strcmp(fname,name) == 0)
  963.             return current;
  964.     if(current != NULL) fclose(current);
  965.     strcpy(fname,name);
  966.     return (current = fopen(name,"rb"));
  967. }
  968.  
  969. /*
  970. ** put_source_line -- print the current source line, along with
  971. ** the line # and file name, if necessary.
  972. */
  973. void
  974. put_source_line(int fmt,char *name,int line) {
  975.     line_info *current = find_file(name);
  976.     FILE *cur;
  977.     if(current == NULL) {
  978.     regular:
  979.       if(fmt == 0)
  980.           printf(" (%s#%d):\n", name, line);
  981.       else
  982.           printf("#%d:\n", line);
  983.     } else {
  984.         char buf[70];
  985.         long offset;
  986.         if((cur = myfopen(name)) == NULL)
  987.             goto regular;
  988.         /*
  989.         ** get the symbol out of virtual memory
  990.         */
  991.         offset = current->offsets[line-1];
  992.         fseek(cur,offset,0);
  993.         /*
  994.         ** truncate line so it fits on screen.
  995.         */
  996.         fgets(buf,sizeof(buf)-2,cur);
  997.         if(strchr(buf,'\n') == NULL)
  998.             strcat(buf,"\n");
  999.         if(fmt == 0)
  1000.             printf(" (%s#%d): %s", name, line,buf);
  1001.         else
  1002.             printf("#%d: %s",line,buf);
  1003.     }
  1004. }
  1005.  
  1006. #endif
  1007.  
  1008.  
  1009. int last_unassemble_unconditional;
  1010. int last_unassemble_jump;
  1011. int last_unassemble_extra_lines;
  1012.  
  1013. word32 unassemble(word32 v, int showregs)
  1014. {
  1015.   int a,b,n,wi, linenum;
  1016.   char *cmp, *brp;
  1017.   word8 *wp;
  1018.   word32 delta;
  1019.   char *name, *lname;
  1020.   long ptracev;
  1021.  
  1022.   default_pick_sign = 0;
  1023.   ansi(A_yellow);
  1024.   last_unassemble_unconditional = 0;
  1025.   last_unassemble_jump = 0;
  1026.   last_unassemble_extra_lines = 0;
  1027.   name = syms_val2name(v, &delta);
  1028.   if (!delta && (name[0] != '0'))
  1029.   {
  1030.     printf("%s()", name);
  1031.     lname = syms_val2line(v, &linenum, 1);
  1032.     if (lname)
  1033. #ifndef SOURCE_LIST
  1034.       printf(" (%s#%d):\n", lname, linenum);
  1035. #else
  1036.       put_source_line(0,lname,linenum);
  1037. #endif
  1038.     else
  1039.       printf(":\n");
  1040.     last_unassemble_extra_lines++;
  1041.   }
  1042.   else
  1043.   {
  1044.     lname = syms_val2line(v, &linenum, 1);
  1045.     if (lname)
  1046.     {
  1047. #ifndef SOURCE_LIST
  1048.       printf("#%d:\n", linenum);
  1049. #else
  1050.       put_source_line(1,lname,linenum);
  1051. #endif
  1052.       last_unassemble_extra_lines++;
  1053.     }
  1054.   }
  1055.  
  1056.   ansi(A_cyan);
  1057.   printf("%08lx: ", v);
  1058. #if 0
  1059.   if (!page_is_valid(v+ARENA) || !page_is_valid(v+5+ARENA))
  1060.   {
  1061.     printf("<bad address>\n");
  1062.     ansi(A_white);
  1063.     return v;
  1064.   }
  1065. #endif
  1066.  
  1067.   ansi(A_blue);
  1068.  
  1069.   prefix = 0;
  1070.   modrmv = sibv = -1;
  1071.   opsize = addrsize = seg_size;
  1072.   vaddr = v;
  1073.   bufp = bufe = 0;
  1074.   col = 0;
  1075.   ubufp = ubuf;
  1076.   ua_str(opmap1[getbyte()]);
  1077.   do {
  1078.     putchar(' ');
  1079.     col++;
  1080.   } while (col < 15);
  1081.   col += strlen(ubuf);
  1082.   do {
  1083.     uputchar(' ');
  1084.     col++;
  1085.   } while (col < 43);
  1086.  
  1087.   ansi(A_red);
  1088.   printf("%s", ubuf);
  1089.  
  1090.   if ((strncmp(ubuf, "jmp ", 4) == 0)
  1091.      || (strncmp(ubuf, "ret", 3) == 0))
  1092.     last_unassemble_unconditional = 1;
  1093.   if (ubuf[0] == 'j')
  1094.     last_unassemble_jump = 1;
  1095.  
  1096.   if (!showregs)
  1097.   {
  1098.     ansi(A_white);
  1099.     putchar('\n');
  1100.     return vaddr;
  1101.   }
  1102.  
  1103.   ansi(A_purple);
  1104.  
  1105.   col -= 43; /* total 25 columns left */
  1106.   cmp = strchr(ubuf+8, ',');
  1107.   brp = strchr(ubuf+8, '[');
  1108.   if (!cmp) cmp = ubuf+8;
  1109.   if (!brp) brp = ubufp;
  1110.   if (brp < cmp) cmp = brp;
  1111.   if (strncmp(ubuf, "mov ", 4))
  1112.     cmp = ubuf+8;
  1113.   for (b=0; b<8; b++)
  1114.   {
  1115.     for (a=2; a>=0; a--)
  1116.     {
  1117.       n = (a==0) ? 1 : ((a==1) ? 2 : 4);
  1118.       if (strstr(cmp, reg_names[a][b]))
  1119.       {
  1120.     col += strlen(reg_names[a][b])+n*2+2;
  1121.     if (col > 29)
  1122.     {
  1123.       printf("\n%53s", "");
  1124.       col = 0;
  1125.     }
  1126.     printf("%s=", reg_names[a][b]);
  1127.     ptracev = ptrace_get_register(reg_index[b] * 4);
  1128.     wp = (char *) &ptracev;
  1129.     while (n)
  1130.     {
  1131.       n--;
  1132.       printf("%02x", wp[n]);
  1133.     }
  1134.     putchar(' ');
  1135.     break;
  1136.       }
  1137.     }
  1138.   }
  1139.   ansi(A_white);
  1140.   putchar('\n');
  1141.   return vaddr;
  1142. }
  1143.